package codec;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import lombok.Getter;
import protocol.Serializer;
import protocol.SerializerAlgorithm;
import protocol.packet.Packet;
import protocol.packet.login.LoginRequest;
import protocol.packet.login.LoginResponse;
import protocol.packet.message.MessageRequest;
import protocol.packet.message.MessageResponse;

public class PacketCodeC {
    private static final int MAGIC_NUMBER = 0x12345678;
    @Getter
    private static PacketCodeC INSTANCE = new PacketCodeC();

    public ByteBuf encode(ByteBuf byteBuf, Packet packet) {
        // 序列化对象
        byte[] data = Serializer.DEFAULT.serialize(packet);

        // header
        byteBuf.writeInt(MAGIC_NUMBER);
        byteBuf.writeByte(packet.getVersion());
        byteBuf.writeByte(Serializer.DEFAULT.getSerializerAlgorithm());
        byteBuf.writeByte(packet.getCommand());
        byteBuf.writeInt(data.length);
        // body
        byteBuf.writeBytes(data);

        return byteBuf;
    }

    public Packet decode(ByteBuf byteBuf) {
        // 按理应该检查魔数，这里业务单一就做简单的跳过处理
        byteBuf.skipBytes(4);

        // 跳过版本号
        byteBuf.skipBytes(1);

        // 序列化方式
        byte serializerAlgorithm = byteBuf.readByte();

        // 指令
        byte command = byteBuf.readByte();

        // 数据包长度
        int length = byteBuf.readInt();
        byte[] data = new byte[length];
        byteBuf.readBytes(data);

        // 反序列化
        Class<? extends Packet> requestType = getRequestType(command);
        Serializer serializer = getSerializer(serializerAlgorithm);
        if(requestType != null && serializer != null) {
            return serializer.deserialize(requestType, data);
        }
        return null;
    }

    private Serializer getSerializer(byte serializerAlgorithm) {
        if(serializerAlgorithm == SerializerAlgorithm.JSON) return Serializer.DEFAULT;
        return null;
    }

    private Class<? extends Packet> getRequestType(byte command) {
        if(command == 1) return LoginRequest.class;
        else if(command == 2) return LoginResponse.class;
        else if(command == 3) return MessageRequest.class;
        else if(command == 4) return  MessageResponse.class;
        return null;
    }

    public static int getMagicNumber() {
        return MAGIC_NUMBER;
    }
}
